using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework;
using ContentRenderingApi;
using ContentRenderingApi.Exceptions;
using ContentRenderingApiSystemTest.Helper;
using ContentRenderingApi.Path;

namespace ContentRenderingApiSystemTest.TestFixture
{
    [TestFixture]
    public class RenderGenericTestFixture
    {
        [Test]
        public void ContentTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "Content");

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.Content.txt"),
                template.Render());
        }

        [Test]
        public void ParameterTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "Parameter");

            template.AddNamedParameter("testa", "test123");
            template.AddNamedParameter("testb");
            template.AddNamedParameter("testb");

            template.AddNamedParameter("testc", "890");
            template.AddNamedParameter("testc", "890");
            template.AddNamedParameter("testd");
            template.AddNamedParameter("teste", true);
            template.AddNamedParameter("testf", false);

            template.AddNamedParameter("anonymous", new {first = "test1", second = "test9"});
            template.AddNamedParameter("anonymous", new {first = "testa", second = "testz"});

            template.AddNamedParameter("anonymous", new { first = new string[] {"test0", "test1"} , second = "testing" });

            template.AddParameter(new { firstNotNamed = new string[] { "test0", "test1" }, secondNotNamed = "testing" });

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.Parameter.txt"),
                template.Render());
        }

        [Test]
        public void IfTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "If");

            template.AddNamedParameter("testb");
            template.AddNamedParameter("testb");
            template.AddNamedParameter("testc");
            template.AddNamedParameter("testc");

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.If.txt"),
                template.Render());
        }

        [Test]
        public void NullTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "Null");

            template.AddNamedParameter("testa", null);
            template.AddNamedParameter("testb", null);
            template.AddNamedParameter("testb", null);
            template.AddNamedParameter("testc", new string[] { null});
            template.AddNamedParameter("testd", new string[] { null, null });

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.Null.txt"),
                template.Render());
        }

        [Test]
        public void ComplexSubstitutionTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "ComplexSubstitution");
            
            List<string> list = new List<string>();
            
            list.Add("098");
            list.Add("765");

            Dictionary<string,int> dictionary = new Dictionary<string,int>();

            dictionary.Add("one", 1);
            dictionary.Add("two", 2);

            template.AddNamedParameter("testa", 123);
            template.AddNamedParameter("testa", 456);
            template.AddNamedParameter("testb", "test123");
            template.AddNamedParameter("testc", list);
            template.AddNamedParameter("testd", dictionary);
            template.AddNamedParameter("teste", new int[] { 1, 2, 3 });
            template.AddNamedParameter("testf", dictionary);
            template.AddNamedParameter("testg", dictionary);
            template.AddNamedParameter("testh", list);
            template.AddNamedParameter("testh", dictionary.Values);
            template.AddNamedParameter("testi", new string[0]);

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.ComplexSubstitution.txt"),
                template.Render());
        }

        [Test]
        public void FunctionTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "Function");

            template.AddNamedParameter("test", "test1");
            template.AddNamedParameter("test", "test2");
            template.AddNamedParameter("test", "test3");
            template.AddNamedParameter("test", "test4");

            CaptureRenderHelper captureRender = new CaptureRenderHelper();

            template.TransformationConfiguration.AddConditionalFunction(new PartialPath("lastOnly"), (value) => value.Position == value.Length);
            template.TransformationConfiguration.AddConditionalFunction(new PartialPath("firstOnly"), (value) => value.Position == 1);
            template.TransformationConfiguration.AddFormattedOutputFunction(new PartialPath("upperCase"), (nodeExtender) => ((string)nodeExtender.RawValue).ToUpper());
            template.TransformationConfiguration.AddFormattedOutputsFunction(new PartialPath("passThrough"), value => new string[] { "1", "9", "3" });
            template.TransformationConfiguration.AddObserverFunction(new PartialPath("capture"), captureRender.ObserverFunctionCallback);
            template.TransformationConfiguration.AddFormattedOutputFunction(new PartialPath("render"), captureRender.FormattedOutputCallback);
            
            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.Function.txt"),
                template.Render());
        }

        [Test]
        public void TemplateDoesNotExistTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "NotFound");

            try
            {
                template.Render();
            }
            catch (TemplateDoesNotExistException)
            {
                return;
            }

            // the exception was throw so fail
            Assert.Fail();
        }

        [Test]
        public void ConditionalTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "Conditional");

            Dictionary<string, string> dictionary = new Dictionary<string, string>();

            dictionary.Add("testa", "");
            dictionary.Add("testb", "");
            dictionary.Add("testd", "");

            template.AddNamedParameter("test", dictionary);

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.Conditional.txt"),
                template.Render());
        }

        [Test]
        public void ListTest()
        {
            AbstractTemplate template = new EmbeddedResourceTemplate(
                Assembly.GetExecutingAssembly(),
                "ContentRenderingApiSystemTest.TestFixture.Input",
                "List");

            List<object> list = new List<object>();

            list.Add(new { test = "testa" });
            list.Add(new { test = "testb" });
            list.Add(new { test = "testc" });

            template.AddParameter(list);

            Assert.AreEqual(
                ResourceHelper.FetchString("ContentRenderingApiSystemTest.TestFixture.Output.List.txt"),
                template.Render());
        }
    }
}
